import { ICleanService } from './../common/dataClean/cleanManager';
import { Employee } from './../domain/model/employee';
import { ExpeditionOrder, ExpeditionOrderItem } from './../domain/model/expeditionOrder';
import { DataContextFactory } from './../domain/fbsDataContext';
import { ServiceException } from "./serviceException";
import { Guid, Logger, ObjectCopier, intersectionArray, uniqueArray, differenceArray } from "../common/utils";
import { Transaction } from "tiny-entity";
import { DateFormat } from "./../common/utils";
import assert = require("assert");
import * as _ from "lodash";
import * as R from "ramda";
import * as moment from "moment";

export class ExpeditionOrderService implements ICleanService {

    get ServiceName() {
        return "expeditionOrderService";
    }

    async CleanData() {
        let ctx = DataContextFactory.GetDataContext();
        const time = moment().startOf('day').subtract(1, 'days').valueOf();
        const result = await ctx.ExpeditionOrder.ToList();
        const orders = result.filter(x => x.beginTime < time);
        for (let data of orders) {
            await this.ctx.Delete(data);
        }
    }

    private get ctx() {
        return DataContextFactory.GetDataContext();
    }

    constructor() {
    }

    async queryExpeditionOrder(params: {
        sourceTerminalIds?: string[],
        status?: Array<string>,
        limit?: number,
        sortby?: string,
        order?: string,
        start?: number,
        end?: number,
        keyWord?: string
    }) {
        let predicates = this.ctx.ExpeditionOrder;
        let result: Array<ExpeditionOrder> = [];
        if (params.status) {
            result = await predicates.Contains(x => x.status, params.status).ToList();
        } else {
            result = await predicates.ToList();
        }
        if (params.keyWord) {
            result = result.filter(order => order.serialNo.indexOf(params.keyWord) > -1 || order.items.some(item => item.extended.table && item.extended.table.name.indexOf(params.keyWord) > -1))
        }
        if (params.sortby) {
            const sort = R.sort((x: ExpeditionOrder, y: ExpeditionOrder) => y[params.sortby] - x[params.sortby]);
            result = sort(result);
        }
        if (params.limit) result.splice(params.limit, result.length);

        if (params.sourceTerminalIds) {
            result = result.filter(x => params.sourceTerminalIds.indexOf(x.sourceTerminalId) > -1)
        }
        if (params.start) {
            result = result.filter(x => x.beginTime > params.start)
        }
        if (params.end) {
            result = result.filter(x => x.beginTime > params.end)
        }
        return result;
    }

    //批量传菜
    async deliveryBatchExpeditionOrder(ids: Array<string>, deliveryer: {
        id: string,
        name: string
    }): Promise<Array<ExpeditionOrder>> {
        // 先检查是否有已经被传走的菜
        let deliveredOrders = this.ctx.ExpeditionOrder.Contains(
            x => x.id,
            ids
        ).Where(
            x => x.status != 'expedited'
            ).ToList();
        if (deliveredOrders && deliveredOrders.length > 0) {
            let expeditionOrder = deliveredOrders[0];
            let msg = '';
            switch (expeditionOrder.status) {
                case 'init':
                    msg = '还未出品';
                    break;
                case 'delivered':
                    msg = '已经被传菜了';
                    break;
                case 'cancel':
                    msg = '已经恢复出品';
                    break;
                default:
                    msg = '不能被传菜';
                    break;
            }
            throw new ServiceException(this, `${expeditionOrder.serialNo} ${expeditionOrder.id} ${msg}`);
        }
        const orders = await Promise.all(ids.map(async id => {
            return await this.deliveryExpeditionOrder(id, deliveryer).then(value => value.currentOrder);
        }));
        return orders;
    }

    //传菜
    async deliveryExpeditionOrder(id, deliveryer: {
        id: string,
        name: string
    }) {
        const expeditionOrder = await this.GetExpeditionOrderById(id);
        if (expeditionOrder.status !== 'expedited') {
            let msg = '';
            switch (expeditionOrder.status) {
                case 'init':
                    msg = '还未出品';
                    break;
                case 'delivered':
                    msg = '已经被传菜了';
                    break;
                case 'cancel':
                    msg = '已经恢复出品';
                    break;
                default:
                    msg = '不能被传菜';
                    break;
            }
            throw new ServiceException(this, expeditionOrder.id + msg);
        }
        expeditionOrder.status = "delivered";
        const now = new Date().getTime();

        const resOrder = await this.ctx.Update(expeditionOrder);
        return {
            currentOrder: resOrder
        }
    }

    //计算ExpeditionOrder的值
    calcOrder(order: ExpeditionOrder) {
        order.qty = order.items.map(x => x.qty - (x.refundQty || 0)).reduce((x, y) => x + y, 0);
        return order;
    }

    /**
     * 通过 id 获取出品单信息
     * 
     * @param {string} orderId 出品单id
     * @returns 出品单信息
     * 
     * @memberOf ExpeditionOrderService
     */
    async GetExpeditionOrderById(orderId: string) {
        const order = await this.ctx.ExpeditionOrder
            .First(
            x => x.id == orderId,
            ['orderId'],
            [orderId]
            );
        if (!order) throw new ServiceException(this, orderId + "没有找到");
        return order;
    }

    /**
     * 获取出品单列表（带查询）
     * @param query 查询参数对象
     * 
     * @memberOf ExpeditionOrderService
     */
    async GetExpeditionOrders(query?: any) {
        // TODO: 没有定查询条件
        let order = this.ctx.ExpeditionOrder.OrderBy(x => x.beginTime);
        return await order.ToList();
    }

    /**
     * 创建出品单
     * @param order 出品盘（单）
     * 
     * @memberOf ExpeditionOrderService
     */
    async CreateExpeditionOrder(order: ExpeditionOrder) {
        let expeditionOrder = new ExpeditionOrder();
        //设置下单时间
        order = expeditionOrder.clone(order, expeditionOrder);
        order.id = Guid.GetGuid();
        const now = new Date().getTime();
        // order.beginTime = now;  beginTime 用传入的参数
        order.finishTime = now;
        order.status = 'expedited';
        order = this.calcOrder(order);
        return await this.ctx.Create(order);
    }

    /**
     * 出品出品单
     * @param orderId 
     */
    async ExpediteExpeditionOrder(orderId: string) {
        let order = await this.ctx.ExpeditionOrder
            .First(
            x => x.id == orderId,
            ['orderId'],
            [orderId]
            );
        if (!order) throw new ServiceException(this, "不存在的出品单！");
        const now = new Date().getTime();
        order.finishTime = now;
        order.status = 'expedited';
        return await this.ctx.Update(order);
    }

    async deleteExpeditionOrderById(id) {
        const order = await this.GetExpeditionOrderById(id);
        order.status = "cancel";
        return await this.ctx.Update(order);
    }
}